const path = require('path');
const express = require('express');
const { createBundleRenderer } = require('vue-server-renderer');
const fs = require('fs');
const chalk = require('chalk');
const favicon = require('serve-favicon');
const LRU = require('lru-cache');

const cookieParser = require('cookie-parser');

const isProd = process.env.NODE_ENV === 'production';

console.log(chalk.blue(`isProd: ${isProd}`));

const app = express();

app.use(cookieParser());

const resolve = (file) => path.resolve(__dirname, file);

let renderer;
let readyPromise;
let template = fs.readFileSync(`./src/index.template.html`, 'utf-8');

let BundleRendererOption = (clientManifest) => {
	return Object.assign(clientManifest, {
		template,
		runInNewContext: false,
		basedir: resolve('./dist')
	});
};

if (isProd) {
	let bundle = require('./dist/vue-ssr-server-bundle.json');
	let clientManifest = require('./dist/vue-ssr-client-manifest.json');
	renderer = createBundleRenderer(bundle,
		BundleRendererOption({ clientManifest }));
}
else {
	readyPromise = require(`./build/setup-dev-server.js`)(app, (bundle, options) => {
		renderer = createBundleRenderer(bundle,
			BundleRendererOption(options));
	});
}

const serve = (path, cache) => express.static(resolve(path), {
	maxAge: cache && isProd ? 60 * 60 * 24 * 30 : 0
});

app.use('/dist', serve('./dist', true));
app.use(favicon('./public/favicon.ico'));

const microCache = LRU({
	max: 1000,
	maxAge: 1000
});

let render = (req, res) => {
	res.setHeader('Content-Type', 'text/html');

	let hit = microCache.get(req.url);
	if (hit) {
		console.log(`hit the cache`);
		res.end(hit);
	}

	let context = {
		title: 'ssr test',
		url: req.url,
		cookies: req.cookies
	};

	renderer.renderToString(context, (err, html) => {
		if (err) {
			switch (err.code) {
				case 404:
					res.end('404 | page not found');
					break;
				case 500:
					res.end('500 | Internal Server Error');
					break;
				default:
					console.log(chalk.red(err));
					res.end('renderToString is Error');
			}
		}
		res.end(html);

		microCache.set(req.url, html);
	});
};

app.listen('8080', () => {
	console.log(`listen at 8080`);
});

app.get('/getCookie', (req, res) => {
	res.end(JSON.stringify(req.cookies));
});

/**
 * 服务器端设置cookie的值，expires为0删除改cookie
 * @param {Object} res = response
 * @param {Object} cookieObj = { cookie_name: { value: '', expires: 1000 } }
 * expires 单位毫秒
 * @returns response
 */
function setCookie (res, cookieObj) {
	Object.keys(cookieObj).forEach((key) => {
		let value = cookieObj[key].value || '';
		if (value instanceof Object) {
			value = JSON.stringify(value);
		}
		let expires = cookieObj[key].expires || 0;
		res.cookie(key, value, { expires: new Date(Date.now() + expires) });
	});
	return res;
}

app.get('/setCookie', (req, res) => {
	res = setCookie(res, {
		'aaa': {
			value: {a: 122},
			expires: 900000
		}
	});
	res.end(JSON.stringify(req.cookies));
});

app.get('*', isProd ? render : (req, res) => {
	console.log(req.cookies);
	console.log(req.url);
	readyPromise.then(() => render(req, res));
});
